<!doctype html>

<html>
<head>
  <link rel="shortcut icon" href="static/images/favicon.ico" type="image/x-icon">
  <title>listformat.js (Closure Library API Documentation - JavaScript)</title>
  <link rel="stylesheet" href="static/css/base.css">
  <link rel="stylesheet" href="static/css/doc.css">
  <link rel="stylesheet" href="static/css/sidetree.css">
  <link rel="stylesheet" href="static/css/prettify.css">

  <script>
     var _staticFilePath = "static/";
     var _typeTreeName = "goog";
     var _fileTreeName = "Source";
  </script>

  <script src="static/js/doc.js">
  </script>


  <meta charset="utf8">
</head>

<body onload="grokdoc.onLoad();">

<div id="header">
  <div class="g-section g-tpl-50-50 g-split">
    <div class="g-unit g-first">
      <a id="logo" href="index.html">Closure Library API Documentation</a>
    </div>

    <div class="g-unit">
      <div class="g-c">
        <strong>Go to class or file:</strong>
        <input type="text" id="ac">
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<h2><a href="local_closure_goog_labs_i18n_listformat.js.html">listformat.js</a></h2>

<pre class="prettyprint lang-js">
<a name="line1"></a>// Copyright 2013 The Closure Library Authors. All Rights Reserved.
<a name="line2"></a>//
<a name="line3"></a>// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
<a name="line4"></a>// you may not use this file except in compliance with the License.
<a name="line5"></a>// You may obtain a copy of the License at
<a name="line6"></a>//
<a name="line7"></a>//      http://www.apache.org/licenses/LICENSE-2.0
<a name="line8"></a>//
<a name="line9"></a>// Unless required by applicable law or agreed to in writing, software
<a name="line10"></a>// distributed under the License is distributed on an &quot;AS-IS&quot; BASIS,
<a name="line11"></a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a name="line12"></a>// See the License for the specific language governing permissions and
<a name="line13"></a>// limitations under the License.
<a name="line14"></a>
<a name="line15"></a>/**
<a name="line16"></a> * @fileoverview List format and gender decision library with locale support.
<a name="line17"></a> *
<a name="line18"></a> * ListFormat takes an array or a var_arg of objects and generates a user
<a name="line19"></a> * friendly list in a locale-sensitive way (i.e. &quot;red, green, and blue&quot;).
<a name="line20"></a> *
<a name="line21"></a> * GenderInfo can be used to determine the gender of a list of items,
<a name="line22"></a> * depending on the gender of all items in the list.
<a name="line23"></a> *
<a name="line24"></a> * In English, lists of items don&#39;t really have gender, and in fact few things
<a name="line25"></a> * have gender. But the idea is this:
<a name="line26"></a> *  - for a list of &quot;male items&quot; (think &quot;John, Steve&quot;) you use &quot;they&quot;
<a name="line27"></a> *  - for &quot;Marry, Ann&quot; (all female) you might have a &quot;feminine&quot; form of &quot;they&quot;
<a name="line28"></a> *  - and yet another form for mixed lists (&quot;John, Marry&quot;) or undetermined
<a name="line29"></a> *    (when you don&#39;t know the gender of the items, or when they are neuter)
<a name="line30"></a> *
<a name="line31"></a> * For example in Greek &quot;they&quot; will be translated as &quot;?????&quot; for masculin,
<a name="line32"></a> * &quot;?????&quot; for feminin, and &quot;????&quot; for neutral/undetermined.
<a name="line33"></a> * (it is in fact more complicated than that, as weak/strong forms and case
<a name="line34"></a> * also matter, see http://en.wiktionary.org/wiki/Appendix:Greek_pronouns)
<a name="line35"></a> *
<a name="line36"></a> */
<a name="line37"></a>
<a name="line38"></a>goog.provide(&#39;goog.labs.i18n.GenderInfo&#39;);
<a name="line39"></a>goog.provide(&#39;goog.labs.i18n.GenderInfo.Gender&#39;);
<a name="line40"></a>goog.provide(&#39;goog.labs.i18n.ListFormat&#39;);
<a name="line41"></a>
<a name="line42"></a>goog.require(&#39;goog.asserts&#39;);
<a name="line43"></a>goog.require(&#39;goog.labs.i18n.ListFormatSymbols&#39;);
<a name="line44"></a>
<a name="line45"></a>
<a name="line46"></a>
<a name="line47"></a>/**
<a name="line48"></a> * ListFormat provides a method to format a list/array of objects to a string,
<a name="line49"></a> * in a user friendly way and in a locale sensitive manner.
<a name="line50"></a> * If the objects are not strings, toString is called to convert them.
<a name="line51"></a> * The constructor initializes the object based on the locale data from
<a name="line52"></a> * the current goog.labs.i18n.ListFormatSymbols.
<a name="line53"></a> *
<a name="line54"></a> * Similar to the ICU4J class com.ibm.icu.text.ListFormatter:
<a name="line55"></a> *   http://icu-project.org/apiref/icu4j/com/ibm/icu/text/ListFormatter.html
<a name="line56"></a> * @constructor
<a name="line57"></a> * @final
<a name="line58"></a> */
<a name="line59"></a>goog.labs.i18n.ListFormat = function() {
<a name="line60"></a>  /**
<a name="line61"></a>   * String for lists of exactly two items, containing {0} for the first,
<a name="line62"></a>   * and {1} for the second.
<a name="line63"></a>   * For instance &#39;{0} and {1}&#39; will give &#39;black and white&#39;.
<a name="line64"></a>   * @private {string}
<a name="line65"></a>   *
<a name="line66"></a>   * Example: for &quot;black and white&quot; the pattern is &quot;{0} and {1}&quot;
<a name="line67"></a>   * While for a longer list we have &quot;cyan, magenta, yellow, and black&quot;
<a name="line68"></a>   * Think &quot;{0} start {1} middle {2} middle {3} end {4}&quot;
<a name="line69"></a>   * The last pattern is &quot;{0}, and {1}.&quot; Note the comma before &quot;and&quot;.
<a name="line70"></a>   * So the &quot;Two&quot; pattern can be different than Start/Middle/End ones.
<a name="line71"></a>   */
<a name="line72"></a>  this.listTwoPattern_ = goog.labs.i18n.ListFormatSymbols.LIST_TWO;
<a name="line73"></a>
<a name="line74"></a>  /**
<a name="line75"></a>   * String for the start of a list items, containing {0} for the first,
<a name="line76"></a>   * and {1} for the rest.
<a name="line77"></a>   * @private {string}
<a name="line78"></a>   */
<a name="line79"></a>  this.listStartPattern_ = goog.labs.i18n.ListFormatSymbols.LIST_START;
<a name="line80"></a>
<a name="line81"></a>  /**
<a name="line82"></a>   * String for the start of a list items, containing {0} for the first part
<a name="line83"></a>   * of the list, and {1} for the rest of the list.
<a name="line84"></a>   * @private {string}
<a name="line85"></a>   */
<a name="line86"></a>  this.listMiddlePattern_ = goog.labs.i18n.ListFormatSymbols.LIST_MIDDLE;
<a name="line87"></a>
<a name="line88"></a>  /**
<a name="line89"></a>   * String for the end of a list items, containing {0} for the first part
<a name="line90"></a>   * of the list, and {1} for the last item.
<a name="line91"></a>   *
<a name="line92"></a>   * This is how start/middle/end come together:
<a name="line93"></a>   *   start = &#39;{0}, {1}&#39;  middle = &#39;{0}, {1}&#39;,  end = &#39;{0}, and {1}&#39;
<a name="line94"></a>   * will result in the typical English list: &#39;one, two, three, and four&#39;
<a name="line95"></a>   * There are languages where the patterns are more complex than
<a name="line96"></a>   * &#39;{1} someText {1}&#39; and the start pattern is different than the middle one.
<a name="line97"></a>   *
<a name="line98"></a>   * @private {string}
<a name="line99"></a>   */
<a name="line100"></a>  this.listEndPattern_ = goog.labs.i18n.ListFormatSymbols.LIST_END;
<a name="line101"></a>};
<a name="line102"></a>
<a name="line103"></a>
<a name="line104"></a>/**
<a name="line105"></a> * Replaces the {0} and {1} placeholders in a pattern with the first and
<a name="line106"></a> * the second parameter respectively, and returns the result.
<a name="line107"></a> * It is a helper function for goog.labs.i18n.ListFormat.format.
<a name="line108"></a> *
<a name="line109"></a> * @param {string} pattern used for formatting.
<a name="line110"></a> * @param {string} first object to add to list.
<a name="line111"></a> * @param {string} second object to add to list.
<a name="line112"></a> * @return {string} The formatted list string.
<a name="line113"></a> * @private
<a name="line114"></a> */
<a name="line115"></a>goog.labs.i18n.ListFormat.prototype.patternBasedJoinTwoStrings_ =
<a name="line116"></a>    function(pattern, first, second) {
<a name="line117"></a>  return pattern.replace(&#39;{0}&#39;, first).replace(&#39;{1}&#39;, second);
<a name="line118"></a>};
<a name="line119"></a>
<a name="line120"></a>
<a name="line121"></a>/**
<a name="line122"></a> * Formats an array of strings into a string.
<a name="line123"></a> * It is a user facing, locale-aware list (i.e. &#39;red, green, and blue&#39;).
<a name="line124"></a> *
<a name="line125"></a> * @param {!Array.&lt;string|number&gt;} items Items to format.
<a name="line126"></a> * @return {string} The items formatted into a string, as a list.
<a name="line127"></a> */
<a name="line128"></a>goog.labs.i18n.ListFormat.prototype.format = function(items) {
<a name="line129"></a>  var count = items.length;
<a name="line130"></a>  switch (count) {
<a name="line131"></a>    case 0:
<a name="line132"></a>      return &#39;&#39;;
<a name="line133"></a>    case 1:
<a name="line134"></a>      return String(items[0]);
<a name="line135"></a>    case 2:
<a name="line136"></a>      return this.patternBasedJoinTwoStrings_(this.listTwoPattern_,
<a name="line137"></a>          String(items[0]), String(items[1]));
<a name="line138"></a>  }
<a name="line139"></a>
<a name="line140"></a>  var result = this.patternBasedJoinTwoStrings_(this.listStartPattern_,
<a name="line141"></a>      String(items[0]), String(items[1]));
<a name="line142"></a>
<a name="line143"></a>  for (var i = 2; i &lt; count - 1; ++i) {
<a name="line144"></a>    result = this.patternBasedJoinTwoStrings_(this.listMiddlePattern_,
<a name="line145"></a>        result, String(items[i]));
<a name="line146"></a>  }
<a name="line147"></a>
<a name="line148"></a>  return this.patternBasedJoinTwoStrings_(this.listEndPattern_,
<a name="line149"></a>      result, String(items[count - 1]));
<a name="line150"></a>};
<a name="line151"></a>
<a name="line152"></a>
<a name="line153"></a>
<a name="line154"></a>/**
<a name="line155"></a> * GenderInfo provides a method to determine the gender of a list/array
<a name="line156"></a> * of objects when one knows the gender of each item of the list.
<a name="line157"></a> * It does this in a locale sensitive manner.
<a name="line158"></a> * The constructor initializes the object based on the locale data from
<a name="line159"></a> * the current goog.labs.i18n.ListFormatSymbols.
<a name="line160"></a> *
<a name="line161"></a> * Similar to the ICU4J class com.icu.util.GenderInfo:
<a name="line162"></a> *   http://icu-project.org/apiref/icu4j/com/ibm/icu/util/GenderInfo.html
<a name="line163"></a> * @constructor
<a name="line164"></a> * @final
<a name="line165"></a> */
<a name="line166"></a>goog.labs.i18n.GenderInfo = function() {
<a name="line167"></a>  /**
<a name="line168"></a>   * Stores the language-aware mode of determining the gender of a list.
<a name="line169"></a>   * @private {goog.labs.i18n.GenderInfo.ListGenderStyle_}
<a name="line170"></a>   */
<a name="line171"></a>  this.listGenderStyle_ = goog.labs.i18n.ListFormatSymbols.GENDER_STYLE;
<a name="line172"></a>};
<a name="line173"></a>
<a name="line174"></a>
<a name="line175"></a>/**
<a name="line176"></a> * Enumeration for the possible ways to generate list genders.
<a name="line177"></a> * Indicates the category for the locale.
<a name="line178"></a> * This only affects gender for lists more than one. For lists of 1 item,
<a name="line179"></a> * the gender of the list always equals the gender of that sole item.
<a name="line180"></a> * This is for internal use, matching ICU.
<a name="line181"></a> * @enum {number}
<a name="line182"></a> * @private
<a name="line183"></a> */
<a name="line184"></a>goog.labs.i18n.GenderInfo.ListGenderStyle_ = {
<a name="line185"></a>  NEUTRAL: 0,
<a name="line186"></a>  MIXED_NEUTRAL: 1,
<a name="line187"></a>  MALE_TAINTS: 2
<a name="line188"></a>};
<a name="line189"></a>
<a name="line190"></a>
<a name="line191"></a>/**
<a name="line192"></a> * Enumeration for the possible gender values.
<a name="line193"></a> * Gender: OTHER means either the information is unavailable,
<a name="line194"></a> * or the person has declined to state MALE or FEMALE.
<a name="line195"></a> * @enum {number}
<a name="line196"></a> */
<a name="line197"></a>goog.labs.i18n.GenderInfo.Gender = {
<a name="line198"></a>  MALE: 0,
<a name="line199"></a>  FEMALE: 1,
<a name="line200"></a>  OTHER: 2
<a name="line201"></a>};
<a name="line202"></a>
<a name="line203"></a>
<a name="line204"></a>/**
<a name="line205"></a> * Determines the overal gender of a list based on the gender of all the list
<a name="line206"></a> * items, in a locale-aware way.
<a name="line207"></a> * @param {!Array.&lt;!goog.labs.i18n.GenderInfo.Gender&gt;} genders An array of
<a name="line208"></a> *        genders, will give the gender of the list.
<a name="line209"></a> * @return {goog.labs.i18n.GenderInfo.Gender} Get the gender of the list.
<a name="line210"></a>*/
<a name="line211"></a>goog.labs.i18n.GenderInfo.prototype.getListGender = function(genders) {
<a name="line212"></a>  var Gender = goog.labs.i18n.GenderInfo.Gender;
<a name="line213"></a>
<a name="line214"></a>  var count = genders.length;
<a name="line215"></a>  if (count == 0) {
<a name="line216"></a>    return Gender.OTHER; // degenerate case
<a name="line217"></a>  }
<a name="line218"></a>  if (count == 1) {
<a name="line219"></a>    return genders[0]; // degenerate case
<a name="line220"></a>  }
<a name="line221"></a>
<a name="line222"></a>  switch (this.listGenderStyle_) {
<a name="line223"></a>    case goog.labs.i18n.GenderInfo.ListGenderStyle_.NEUTRAL:
<a name="line224"></a>      return Gender.OTHER;
<a name="line225"></a>    case goog.labs.i18n.GenderInfo.ListGenderStyle_.MIXED_NEUTRAL:
<a name="line226"></a>      var hasFemale = false;
<a name="line227"></a>      var hasMale = false;
<a name="line228"></a>      for (var i = 0; i &lt; count; ++i) {
<a name="line229"></a>        switch (genders[i]) {
<a name="line230"></a>          case Gender.FEMALE:
<a name="line231"></a>            if (hasMale) {
<a name="line232"></a>              return Gender.OTHER;
<a name="line233"></a>            }
<a name="line234"></a>            hasFemale = true;
<a name="line235"></a>            break;
<a name="line236"></a>          case Gender.MALE:
<a name="line237"></a>            if (hasFemale) {
<a name="line238"></a>              return Gender.OTHER;
<a name="line239"></a>            }
<a name="line240"></a>            hasMale = true;
<a name="line241"></a>            break;
<a name="line242"></a>          case Gender.OTHER:
<a name="line243"></a>            return Gender.OTHER;
<a name="line244"></a>          default: // Should never happen, but just in case
<a name="line245"></a>            goog.asserts.assert(false,
<a name="line246"></a>                &#39;Invalid genders[&#39; + i + &#39;] = &#39; + genders[i]);
<a name="line247"></a>            return Gender.OTHER;
<a name="line248"></a>        }
<a name="line249"></a>      }
<a name="line250"></a>      return hasMale ? Gender.MALE : Gender.FEMALE;
<a name="line251"></a>    case goog.labs.i18n.GenderInfo.ListGenderStyle_.MALE_TAINTS:
<a name="line252"></a>      for (var i = 0; i &lt; count; ++i) {
<a name="line253"></a>        if (genders[i] != Gender.FEMALE) {
<a name="line254"></a>          return Gender.MALE;
<a name="line255"></a>        }
<a name="line256"></a>      }
<a name="line257"></a>      return Gender.FEMALE;
<a name="line258"></a>    default:
<a name="line259"></a>      return Gender.OTHER;
<a name="line260"></a>  }
<a name="line261"></a>};
</pre>


</body>
</html>
